
import { ziBi_json } from "../configs/ziBi_json";
import { ziDi_json } from "../configs/zi_json";
import { ziDi_jsonWT } from "../configs/zi_jsonTwo";
import superManager from "./superManager";

export interface ziBi {
    //ID 建议用字
    id: string,
    //
    name: string,
    //说明
    explain: string,
}

//组合坐标
export interface makePos {
    start: number;
    end: number;
}

//组成
export interface ziMake {
    //一个字
    z: string;
    //一个笔划
    b: string;
    /** 允许的位置信息 如没有 则无框内规则
     *   田
     *   1 2 3
     *   4 5 6
     *   7 8 9
     */
    zbPoss: makePos[],
}

export interface ziDi {
    //ID建议用字
    id: string;
    //
    name: string;
    //总笔划
    biCount: number;
    //拼音
    py: string;
    //说明
    explain: string;
    //可来自组合
    makeList?: ziMake[];
    //有序笔划组成
    orderBiList?: string[];
}

export class ziBiMap {
    [id: string]: ziBi;
}

export class ziDiMap {
    [id: string]: ziDi;
}

export default class ziManager extends superManager {

    //
    protected className: string = '字管理';
    //字表映射
    private m_ziBiList: ziBi[] = [];
    private m_ziBiMap: ziBiMap = new ziBiMap();
    //字表 按笔画的2维数组
    private m_ziDiList: ziDi[] = [];
    private m_ziDiHuaList: ziDi[][] = [];
    private m_ziDiHuaMap: ziDiMap[] = [];
    private m_ziDiMap: ziDiMap = new ziDiMap();
    //字表 按笔画的2维数组 俩笔模式
    private m_ziDiListOfWT: ziDi[] = [];
    private m_ziDiHuaListOfWT: ziDi[][] = [];
    private m_ziDiHuaMapOfWT: ziDiMap[] = [];
    private m_ziDiMapOfWT: ziDiMap = new ziDiMap();

    loadManager() {
        return new Promise<void>((resolve,reject)=>{
            super.loadManager();
            //字
            this.m_ziBiList = ziBi_json();
            for (let zb of this.m_ziBiList) {
                this.m_ziBiMap[zb.id] = zb;
            }
            //字笔划
            this.m_ziDiList = ziDi_json();
            for (let zd of this.m_ziDiList) {
                let {biCount} = zd;
                //
                if (null == this.m_ziDiHuaList[biCount]) {
                    this.m_ziDiHuaList[biCount] = [];
                }
                this.m_ziDiHuaList[biCount].push(zd);
                //笔划MAP
                if (null == this.m_ziDiHuaMap[biCount]) {
                    this.m_ziDiHuaMap[biCount] = new ziDiMap();
                }
                this.m_ziDiHuaMap[biCount][zd.id] = zd;
                //
                this.m_ziDiMap[zd.id] = zd;
            }
            this.m_ziDiListOfWT = ziDi_jsonWT();
            for (let zd of this.m_ziDiListOfWT) {
                let {biCount} = zd;
                //
                if (null == this.m_ziDiHuaListOfWT[biCount]) {
                    this.m_ziDiHuaListOfWT[biCount] = [];
                }
                this.m_ziDiHuaListOfWT[biCount].push(zd);
                //笔划MAP
                if (null == this.m_ziDiHuaMapOfWT[biCount]) {
                    this.m_ziDiHuaMapOfWT[biCount] = new ziDiMap();
                }
                this.m_ziDiHuaMapOfWT[biCount][zd.id] = zd;
                //
                this.m_ziDiMapOfWT[zd.id] = zd;
            }
            resolve();
        });
    }

    /**
     * 获取字信息
     * @param id
     */
    getZiDiInfo(id: string) {
        return this.m_ziDiMap[id];
    }
    getZiDiInfoOfWT(id: string) {
        return this.m_ziDiMapOfWT[id];
    }
    /**
     * 获取指定笔画数所有字
     * @param biCount
     */
    getZiDiMapOfBiCount(biCount: number): ziDiMap {
        return this.m_ziDiHuaMap[biCount];
    }
    getZiDiMapOfBiCountOfWT(biCount: number): ziDiMap {
        return this.m_ziDiHuaMapOfWT[biCount];
    }

    /**
     * 获取笔划信息
     * @param id
     * */
    getZiBiInfo(id: string) {
        return this.m_ziBiMap[id];
    }

    getMakeZi(zId: string, bId: string, makeP: makePos): string {
        let zInfo = this.getZiDiInfo(zId);
        //
        let descBiCount = zInfo.biCount + 1;
        //获取对应笔画的字
        let ziMap = this.getZiDiMapOfBiCount(descBiCount);
        //
        let isHaveBf: boolean = false;
        //
        for (let ziId in ziMap) {
            let zi = ziMap[ziId];
            //
            if (!zi.makeList) continue;
            for (let make of zi.makeList) {
                //单字 和 字笔划对应
                if (make.z == zId && make.b == bId) {
                    isHaveBf = true;
                    //并且位置合法
                    for (let pos of make.zbPoss) {
                        if (makeP.start == pos.start && makeP.end == pos.end) {
                            return ziId;
                        }
                    }
                }
            }
        }
        if (isHaveBf) {
            return 'have';
        }
        return null;
    }
    getMakeZiEx(zId: string, bId: ziBi[], makeP: makePos[]): string {
        let zInfo = this.getZiDiInfoOfWT(zId);
        //
        let descBiCount = zInfo.biCount + 2;
        //获取对应笔画的字
        let ziMap = this.getZiDiMapOfBiCountOfWT(descBiCount);
        //
        let isHaveBf: boolean = false;
        //
        for (let ziId in ziMap) {
            let zi = ziMap[ziId];
            //
            if (!zi.makeList) continue;
            for (let make of zi.makeList) {
                //
                let ziBiArray: string[] = make.b.split(" ", 2);
                if (!(make.z == zId)) continue;
                let eachOfWord: ziMake[] = this.splitZbPosArray(zId,ziBiArray, make.zbPoss);

                //单字 和 字笔划对应
                if (make.z == zId) {
                    isHaveBf = true;
                    //并且位置合法
                    let location: boolean = this.isLocation(makeP,eachOfWord,bId);
                    if (location){
                        return ziId;
                    }
                }
            }
        }
        if (isHaveBf) {
            return 'have';
        }
        return null;
    }
     /**
     * 判断笔划对应位置是否合法
     * @param finger 
     * @param afterSplit
     * @param wStructArray
     * @return ziMake[]
     */
    isLocation(finger: makePos[], afterSplit: ziMake[], wStructArray: ziBi[]): boolean{
        let isLocaLeagl: boolean = false;
        let isFristLegl:boolean = false;//第一笔合法
        for (let iWStruct of wStructArray){
            for(let iZiMake of afterSplit){            
                if (iZiMake.b == iWStruct.id){
                    for (let pos of iZiMake.zbPoss) {
                        //第一笔
                        if (!isFristLegl && finger[0].start == pos.start && finger[0].end == pos.end) {
                            isFristLegl = true;
                            break;  
                        }
                        if (isFristLegl && finger[1].start == pos.start && finger[1].end == pos.end){
                            isLocaLeagl = true;
                            break; 
                        }
                    }
                    afterSplit = afterSplit.filter(item => item != iZiMake);
                    break;
                }
            }
        }
        return isLocaLeagl
    }
    /**
     * 根据start：0 end：0划分数组 每一笔划对应一个位置数组
     * @param zId  
     * @param wordTwo(俩笔)
     * @param posArrOfMPos
     * @return ziMake[]
     */
    splitZbPosArray(zId:string, wordTwo: string[], posArrOfMPos: makePos[]): ziMake[]{
        //
        let ziMakeArray: ziMake[] = [];
        let isSentinel: boolean = false;//哨兵start:0 end:0 
        // let isSentinels: number = 0;//哨兵start:0 end:0        
        let mPosFrist: makePos[] = [];
        let mPosSecond: makePos[] = [];
        let array: any = {};
        for(let pos of posArrOfMPos){
            if(!(pos.start == 0 && pos.end == 0)){
                if (isSentinel){
                    mPosSecond.push(pos);
                    // array[isSentinels].zbPoss.push(pos);
                    continue;
                }
                mPosFrist.push(pos); 
            } 
            if(pos.start == 0 && pos.end == 0){
                isSentinel = true;
                // isSentinels++;
                continue;
            }  
        }
        for(let index = 0; index < wordTwo.length; index++){
            let ziMakeMessage: ziMake;
            if (index == 0){
                ziMakeMessage = {
                    z : zId,
                    b : wordTwo[index],
                    zbPoss : mPosFrist,
                }
            }
            if (index == 1){
                ziMakeMessage = {
                    z : zId,
                    b : wordTwo[index],
                    zbPoss : mPosSecond,
                }
            }
            ziMakeArray.push(ziMakeMessage); 
        }
         
        return ziMakeArray;
    }
    /**
     * 获取坐标对应的田字坐标
     * @param vc2
     */
    getMakePosOfVec2(vc2: cc.Vec2, size: cc.Size): number {
        let oneSize = size.width / 3;
        let oneHref = oneSize / 2;
        //
        let x = 1;
        if (vc2.x > -oneHref && vc2.x < oneHref) x = 2;
        else if (vc2.x > oneHref) x = 3;
        //
        let y = 0;
        if (vc2.y < oneHref && vc2.y > -oneHref) y = 1;
        else if (vc2.y < -oneHref) y = 2;
        //
        let xy = y * 3 + x;
        return xy;
    }

    /**
     * 获取能组成的所有字
     * @param srcZiId 单字
     */
    getCanMakeDoZiIds(srcZiId: string): string[] {
        let srcZiInfo = this.getZiDiInfo(srcZiId);
        let allCountZis = this.getZiDiMapOfBiCount(srcZiInfo.biCount + 1);
        let ziIdList: string[] = [];
        for (let id in allCountZis) {
            let zi = allCountZis[id];
            //
            if (!zi.makeList) continue;
            for (let make of zi.makeList) {
                if (make.z == srcZiId) {
                    ziIdList.push(zi.id);
                }
            }
        }
        return ziIdList;
    }
    /**
     * 获取能组成的所有字 俩笔
     * @param srcZiId 单字
     */
    getCanMakeDoZiIdsEx(srcZiId: string): string[] {
        let srcZiInfo = this.getZiDiInfoOfWT(srcZiId);
        let allCountZis = this.getZiDiMapOfBiCountOfWT(srcZiInfo.biCount + 2);
        let ziIdList: string[] = [];
        for (let id in allCountZis) {
            let zi = allCountZis[id];
            //
            if (!zi.makeList) continue;
            for (let make of zi.makeList) {
                if (make.z == srcZiId) {
                    ziIdList.push(zi.id);
                }
            }
        }
        return ziIdList;
    }

    /**
     * 查找能组成的字
     * @param biIds 有序笔划
     * */
    findCanMakZiIds(biIds: string[]): string[] {
        let biCount = biIds.length;
        let srcZiArray = this.getZiDiMapOfBiCount(biCount);
        let ziOks: string[] = [];
        //
        for (let id in srcZiArray) {
            let zi = srcZiArray[id];
            if (this.isCalcSuccessZiIdOfBiIds(zi, biIds)) {
                ziOks.push(zi.id);
            }
        }
        //
        return ziOks;
    }
    findCanMakZiIdsOfWT(biIds: string[]): string[] {
        let biCount = biIds.length;
        let srcZiArray = this.getZiDiMapOfBiCountOfWT(biCount);
        let ziOks: string[] = [];
        //
        for (let id in srcZiArray) {
            let zi = srcZiArray[id];
            if (this.isCalcSuccessZiIdOfBiIds(zi, biIds)) {
                ziOks.push(zi.id);
            }
        }
        //
        return ziOks;
    }


    /**
     * 是否匹配
     * @param ziId 字ID
     * @param biIds 笔划有序ID
     */
    private isCalcSuccessZiIdOfBiIds(ziInfo: ziDi, biIds: string[]): boolean {
        //
        const {orderBiList} = ziInfo;
        //
        if (!orderBiList) return false;
        //
        if (biIds.length != orderBiList.length) {
            return false;
        }
        //
        const needRightCount = orderBiList.length;
        //容错次数
        let canWrongCount = 0;
        if (needRightCount >= 20) {
            canWrongCount = 2;
        } else if (needRightCount >= 10) {
            canWrongCount = 1;
        } else {
            canWrongCount = 0;
        }
        for (let i = 0; i < biIds.length; i++) {
            if (biIds[i] == orderBiList[i]) continue;
            //模糊判断
            if (orderBiList[i] == '丶' && biIds[i] == '㇏') {
            } else {
                canWrongCount--;
            }
            //错次数太多
            if (canWrongCount < 0) {
                return false;
            }
        }
        return true;
    }
}






















